﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

using MultiVolumeControl.Core;

namespace MultiVolumeControl.Win32
{
	public class MvcTrayApp : Form
	{
		private readonly IDictionary<string,AudioWrapper> devices;
		private readonly NotifyIcon trayIcon;
		private readonly ContextMenu trayMenu;
		private readonly HotKeyCatcher catcher;
		
		public MvcTrayApp()
		{
			// Init devices
			devices = MiscUtils.GetDeviceMap();
			// Init system tray
			trayMenu = new ContextMenu();
			foreach(var device in devices){
				var local = device;
				trayMenu.MenuItems.Add(local.Key, new [] {
				                       	new MenuItem("Mute",(o,e) => local.Value.Mute = true),
				                       	new MenuItem("UnMute",(o,e) => local.Value.Mute = false),
				                       	new MenuItem("Set to 0 %",(o,e)=>local.Value.MasterVolumeLevelScalar=0),
				                       	new MenuItem("Set to 25 %",(o,e)=>local.Value.MasterVolumeLevelScalar=0.25F),
				                       	new MenuItem("Set to 50 %",(o,e)=>local.Value.MasterVolumeLevelScalar=0.50F),
				                       	new MenuItem("Set to 75 %",(o,e)=>local.Value.MasterVolumeLevelScalar=0.75F),
				                       	new MenuItem("Set to 100 %",(o,e)=>local.Value.MasterVolumeLevelScalar=1)
				                       });
			}
			trayMenu.MenuItems.Add("-");
			var appCfg = ConfigurationManager.AppSettings;
			var muteAll = MiscUtils.ParseHotKey(appCfg, "MuteAll");
			trayMenu.MenuItems.Add("Mute all"+MiscUtils.AsString(muteAll),MuteAll);
			var unmuteAll = MiscUtils.ParseHotKey(appCfg, "UnmuteAll");
			trayMenu.MenuItems.Add("UnMute all"+MiscUtils.AsString(unmuteAll),UnmuteAll);
			var setAll0 = MiscUtils.ParseHotKey(appCfg, "SetAll0");
			trayMenu.MenuItems.Add("Set all to 0 %"+MiscUtils.AsString(setAll0),SetAll0);
			var setAll25 = MiscUtils.ParseHotKey(appCfg, "SetAll25");
			trayMenu.MenuItems.Add("Set all to 25 %"+MiscUtils.AsString(setAll25),SetAll25);
			var setAll50 = MiscUtils.ParseHotKey(appCfg, "SetAll50");
			trayMenu.MenuItems.Add("Set all to 50 %"+MiscUtils.AsString(setAll50),SetAll50);
			var setAll75 = MiscUtils.ParseHotKey(appCfg, "SetAll75");
			trayMenu.MenuItems.Add("Set all to 75 %"+MiscUtils.AsString(setAll75),SetAll75);
			var setAll100 = MiscUtils.ParseHotKey(appCfg, "SetAll100");
			trayMenu.MenuItems.Add("Set all to 100 %"+MiscUtils.AsString(setAll100),SetAll100);
			trayMenu.MenuItems.Add("-");
			trayMenu.MenuItems.Add("About...", OnAbout);
			trayMenu.MenuItems.Add("-");
			trayMenu.MenuItems.Add("Quit", OnQuit);
			// Init tray icon
			trayIcon = new NotifyIcon();
			trayIcon.Text = "MultiVolumeControl";
			this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
			trayIcon.Icon = this.Icon;
			trayIcon.ContextMenu = trayMenu;
			trayIcon.Visible = true;
			// Register hot keys
			catcher = new HotKeyCatcher();
			catcher.HotKeyPressed+= new HotKeyEventHandler(catcher_HotKeyPressed);
			Register("MuteAll", muteAll);
			Register("UnmuteAll", unmuteAll);
			Register("SetAll0", setAll0);
			Register("SetAll25", setAll25);
			Register("SetAll50", setAll50);
			Register("SetAll75", setAll75);
			Register("SetAll100", setAll100);
		}
		
		private void Register(string name, Tuple<ModifierKeys,Keys> tuple)
		{
			if(tuple == null)
				return;
			if(!catcher.Register(name, tuple))
				MessageBox.Show(string.Format("Could not register hot key '{0}' (Modifier = {1}, Key = {2})!",
				                              name, tuple.Item1, tuple.Item2));
		}
		
		#region Set level for all
		private void SetAllTo(float level){
			foreach(var d in devices)
				d.Value.MasterVolumeLevelScalar=level;
		}
		
		private void SetAll0(object sender, EventArgs e){ SetAllTo(0); }
		private void SetAll25(object sender, EventArgs e){ SetAllTo(0.25F); }
		private void SetAll50(object sender, EventArgs e){ SetAllTo(0.50F); }
		private void SetAll75(object sender, EventArgs e){ SetAllTo(0.75F); }
		private void SetAll100(object sender, EventArgs e){ SetAllTo(1); }
		#endregion

		#region Set mute for all
		private void SetAllMuteTo(bool value){
			foreach(var d in devices)
				d.Value.Mute=value;
		}
		
		private void MuteAll(object sender, EventArgs e){ SetAllMuteTo(true); }
		private void UnmuteAll(object sender, EventArgs e){	SetAllMuteTo(false); }
		#endregion
		
		private void catcher_HotKeyPressed(object sender, HotKeyEventArgs e)
		{
			var method = GetType().GetMethod(e.Name, BindingFlags.NonPublic | BindingFlags.Instance);
			if(method==null)
				return;
			method.Invoke(this, new object[] { sender, null });
		}
		
		private void OnQuit(object sender, EventArgs e){
			Dispose(true);
			Application.Exit();
		}
		
		private void OnAbout(object sender, EventArgs e){
			var text = "MultiVolumeControl v.0.5" + Environment.NewLine + "Copyright (C) 2012 by Harry Blauberg"
				+ Environment.NewLine + Environment.NewLine
				+ "uses NAudio 1.5 (http://naudio.codeplex.com/)";
			MessageBox.Show(text, "About this app", MessageBoxButtons.OK, MessageBoxIcon.Information);			
		}

		protected override void OnLoad(EventArgs e)
		{
			Visible=false;
			ShowInTaskbar=false;
			base.OnLoad(e);
		}
		
		protected override void Dispose(bool disposing)
		{
			if(disposing){
				devices.Clear();
				trayIcon.Dispose();
				trayMenu.Dispose();
				catcher.Dispose();
			}
			base.Dispose(disposing);
		}
	}
}